<cfcomponent displayname="PersistenceService" output="false">

	<cffunction name="init" returntype="any" output="false" hint="Constructor">
		<cfargument name="adapter" required="true">
		<cfset variables.adapter = adapter />
		<cfreturn this />
	</cffunction>

	<cffunction name="setAdapter" returntype="void" access="public" output="false" hint="">
		<cfargument name="adapter" required="true"/>
		<cfset variables.adapter = arguments.adapter />
	</cffunction>

	<cffunction name="getAdapter" returntype="any" output="false" hint="gets adapter">
		<cfreturn variables.adapter />
	</cffunction>

	<cffunction name="query" returntype="any" output="false" hint="Create Project Object">
		<cfargument name="ormobjectname" required="true">
		<cfargument name="criteria" default="#structNew()#" type="struct">
		<cfargument name="fields" type="string" default="" />
		<cfargument name="orderColumn" type="string" default="" />
		<cfargument name="orderAscending" type="boolean"  default="true" />
<!---
 todo: fixme
		<cfargument name="queryargs" default="" _type="struct">
		<cfset var arg = "" />
		<cfif isStruct(queryargs)>
			<cfloop list="#structKeyList(queryargs)#" index="#arg#">
				<cfset orderColumn = queryargs["orderColumn"]>
			</cfloop>
 			<cfargument name="orderColumn" type="string" required="false" />
			<cfargument name="orderAscending" type="boolean" required="false" default="true" />
			<cfargument name="gatewayMethod" type="string" required="false" />
			<cfargument name="gatewayBean" type="string" required="false" />
		</cfif>
 --->
		<cfreturn getAdapter().list(arguments.ormobjectname,arguments.criteria,fields,arguments.orderColumn,arguments.orderAscending) />
	</cffunction>

	<cffunction name="load" returntype="any" output="false" access="public">
		<cfargument name="ormobjectname" type="string" required="true" />
		<cfargument name="primaryKeys" type="struct" required="true" />
			<cfreturn getAdapter().read(arguments.ormobjectname,arguments.primaryKeys) />
	</cffunction>

	<cffunction name="getObjectMetadata" access="public" returntype="any" output="false" roles="" hint="Returns last classname element">
		<cfargument name="ormobjectname" type="string" required="true" />
			<cfreturn getAdapter().getObjectMetadata(arguments.ormobjectname) />	
	</cffunction>


	<cffunction name="getMetaORM" access="private" returntype="any" output="false" roles="" hint="Returns last classname element">
		<cfargument name="persistedObject" required="true" />
		<cfset var meta = getMetaData(persistedObject)>
		<cfset var ormname = "">
		<cfif NOT structKeyExists(meta,"ormobjectname")>
			<cfthrow type="PersistenceService.noOrmObjectNameError" message="No ORM Object Name metadata for : #meta["name"]#">
		<cfelse>
			<cfreturn meta["ormobjectname"]>
		</cfif>
	</cffunction>

	<cffunction name="persist" returntype="any" output="false" hint="Create Project Object">
		<cfargument name="ormobjectname" type="string" required="true" />
		<cfargument name="persistObject" required="true">
		<cfargument name="persistObjectValues" default="">
		<cfset var validation = "">
		<cfif isStruct(persistObjectValues)>
			<cfloop list="#structKeyList(arguments.persistObjectValues)#" index="val">
				<cfinvoke component="#arguments.persistObject#" method="set#val#">
					<cfinvokeargument name="#val#" value="#persistObjectValues[val]#" />
				</cfinvoke>			
			</cfloop>				
		</cfif>
		<cfset validation =  getAdapter().validate(arguments.ormobjectname,arguments.persistObject) />
		<cfif NOT validation.hasErrors()>
			<cfset getAdapter().commit(arguments.ormobjectname,arguments.persistObject) />
		</cfif>
		<cfreturn validation />
	</cffunction>

	<cffunction name="persisted" returntype="any" output="false" hint="Create Project Object">
		<cfargument name="persistedObject" required="true">
		<cfreturn getAdapter().persisted(arguments.persistedObject) />
	</cffunction>

	<cffunction name="populate" access="public" hint="I populate the record from any bean passed in.  I match up getters on the bean with setters on the record" output="false" returntype="void">
		<cfargument name="destBean" hint="I am the Bean to populate." required="yes" type="any" _type="any" />
		<cfargument name="sourceBean" hint="I am the Bean to populate from." required="yes" type="any" _type="any" />
		<cfargument name="ignoreEmpty" hint="ignore empty setters?" default="false" type="any" _type="boolean" />
		<cfset var ThisFunctionArray = StructKeyArray(destBean) />
		<cfset var BeanFunctionArray = StructKeyArray(arguments.sourceBean) />
		<cfset var x = 0 />
		<cfset var y = 0 />
		<cfset var value = 0 />
		<cfset var argumentName = 0 />
		
		<!--- look for setters --->
		<cfloop from="1" to="#ArrayLen(ThisFunctionArray)#" index="x">
			<cfif left(ThisFunctionArray[x], 3) IS "set" AND ArrayLen(getMetadata(arguments.destBean[ThisFunctionArray[x]]).parameters) IS 1>
				<!--- get the argument name --->
				<cfset argumentName = getMetadata(arguments.destBean[ThisFunctionArray[x]]).parameters[1].name />
				<!--- look for getters --->
				<cfloop from="1" to="#ArrayLen(BeanFunctionArray)#" index="y">
					<cfif BeanFunctionArray[y] IS "get" & right(ThisFunctionArray[x], len(ThisFunctionArray[x]) - 3) AND ArrayLen(getMetadata(arguments.sourceBean[BeanFunctionArray[y]]).parameters) IS 0>
						<!--- get the data --->
						<cfinvoke component="#arguments.sourceBean#" method="#BeanFunctionArray[y]#" returnvariable="value" />
						<!--- set the data --->
						<cfif  ignoreEmpty AND value eq "">
							<!--- do nothing --->
						<cfelse>
							<cfinvoke component="#arguments.destBean#" method="#ThisFunctionArray[x]#">
								<cfinvokeargument name="#argumentName#" value="#value#" />
							</cfinvoke>					
						</cfif>
					</cfif>
				</cfloop>
			</cfif>
		</cfloop>		
	</cffunction>


</cfcomponent>